﻿using System;
using System.IO;
using System.Text;
using System.Net;
using System.Net.Http;
using JDCloudSDK.Core.Auth;
using JDCloudSDK.Core.Extensions;
using PdfSharp.Pdf;
using PdfSharp.Drawing;
using Newtonsoft.Json.Linq;
using TrinityAPI.Base;
using TrinityAPI.Base.Tools;
using TrinityAPI.Base.Models;
using System.Collections.Generic;

namespace Express.JDWuJie
{
    public class GetWaybill : IAction
    {
        private string courierCode;
        private string eShopCode;
        private bool receiverLock;

        public JToken Invoke(JObject dataset, params JToken[] args)
        {
            var arguments = args.Length > 0 ? args[0] as JObject : null;
            var request = dataset.GetJsonObject("request");
            var constant = dataset.GetJsonObject("constant");
            var connection = constant.GetJsonObject("connection");
            var o2o = connection.GetJsonObject("o2o");
            
            eShopCode = arguments.GetJsonObjectStringValue("eShopCode");
            receiverLock = arguments.GetJsonObjectBooleanValue("receiverLock");
            string courierCompCode = request.GetNecessaryJsonObjectStringValue("courierCode", "request");
            var config = constant.GetNecessaryJsonObject("jingdongWaybillConfig", "constant");

            string sql = "select ExtItemCode from O2O_MasterConvert where MasterType='CourierCompany' and DisabledFlag=0 and ExternalSystem='JDWUJIE' and ItemCode=@courierCompCode";
            var dbBase = Utils.GetDBAdapter("o2o", o2o, null, false);
            var ds = dbBase.Query(sql, new List<DBParameter>() { new DBParameter("@courierCompCode", courierCompCode) }, System.Data.CommandType.Text);
            if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
                courierCode = ds.Tables[0].Rows[0][0].ToString();

            return CreateWaybill(request, config);
        }

        public JObject CreateWaybill(JObject request, JObject config)
        {
            string path = "constant.jingdongWaybillConfig";
            string url = config.GetNecessaryJsonObjectStringValue("url", path);
            string appkey = config.GetNecessaryJsonObjectStringValue("appkey", path);
            string appsecret = config.GetNecessaryJsonObjectStringValue("appsecret", path);
            string customerId = config.GetNecessaryJsonObjectStringValue("customerid", path);
            string method = config.GetJsonObjectStringValue("default_method", "jingdong.hufu.order.popOrderSearch");
            var proxy = config.GetJsonObjectValue("proxy");
            string ecomOrderId = request.GetJsonObjectStringValue("ecom_orderid");
            string orderId = request.GetNecessaryJsonObjectStringValue("orderid");
            string deliverOrderId = request.GetJsonObjectStringValue("deliverOrderId", orderId);

            var credentials = new Credentials(appkey, appsecret);

            string j_address = request.GetJsonObjectStringValue("from_address");
            string j_contact = request.GetJsonObjectStringValue("from_contact");
            string j_tel = request.GetJsonObjectStringValue("from_phone");
            string j_mobile = request.GetJsonObjectStringValue("from_mobile");

            int packageNo = request.GetJsonObjectIntValue("package_no");
            int packageTotal = request.GetJsonObjectIntValue("package_total");

            JObject param = new JObject();
            param["platformOrderNo"] = ecomOrderId;
            param["vendorOrderCode"] = deliverOrderId;
            param["providerCode"] = courierCode;
            param["skuList"] = request.GetJsonObjectValue("cargoes");
            param["package_no"] = packageNo;
            param["package_total"] = packageTotal;
            param["fromAddress"] = SplitAddress(j_address);
            param["fromAddress"]["contact"] = j_contact;
            param["fromAddress"]["phone"] = string.IsNullOrWhiteSpace(j_tel) ? j_mobile : j_tel;
            param["fromAddress"]["mobile"] = string.IsNullOrWhiteSpace(j_mobile) ? j_tel : j_mobile;
            if (receiverLock)
            {
                string d_address = request.GetJsonObjectStringValue("to_address");
                string d_contact = request.GetJsonObjectStringValue("to_contact");
                string d_tel = request.GetJsonObjectStringValue("to_phone");
                string d_mobile = request.GetJsonObjectStringValue("to_mobile");

                string d_province = null;
                string d_city = null;
                string d_country = null;
                string d_detailaddress = null;
                string[] d_addresses = d_address.Trim().Split(' ');
                if (d_addresses.Length > 3)
                {
                    d_province = d_addresses[0];
                    d_city = d_addresses[1];
                    d_country = d_addresses[2];
                    d_detailaddress = d_province + d_city + d_country + d_address.Substring(d_province.Length + d_city.Length + d_country.Length);

                    param["toAddress"] = new JObject()
                    {
                        { "provinceName", d_province },
                        { "cityName", d_city },
                        { "countryName", d_country },
                        { "address",  d_detailaddress }
                    };
                }
                else
                {
                    param["toAddress"] = SplitAddress(d_address);
                }

                param["toAddress"]["contact"] = d_contact;
                param["toAddress"]["phone"] = string.IsNullOrWhiteSpace(d_tel) ? d_mobile : d_tel;
                param["toAddress"]["mobile"] = string.IsNullOrWhiteSpace(d_mobile) ? d_tel : d_mobile;
            }

            JObject extendProps = new JObject()
            {
                { "method", "jingdong.ldop.waybill.receive" },
                { "eShopCode", eShopCode },
                { "params", param }
            };

            JObject apiRequest = new JObject()
            {
                { "extendProps", extendProps }
            };

            string requestString = apiRequest.ToString(Newtonsoft.Json.Formatting.None);

            try
            {
                var proxyHttpClientHandler = new HttpClientHandler();

                if (proxy != null && proxy.Type == JTokenType.String && !string.IsNullOrWhiteSpace(proxy.ToString()) && proxy.ToString().IndexOf(":") > -1)
                {
                    string[] hostAndPort = proxy.ToString().Split(':');
                    int port = 0;
                    if (int.TryParse(hostAndPort[1], out port))
                    {
                        proxyHttpClientHandler.Proxy = new WebProxy(hostAndPort[0], port);
                        proxyHttpClientHandler.UseProxy = true;
                    }
                }
                else if (proxy != null && proxy.Type == JTokenType.Boolean && !proxy.Value<bool>())
                {
                    proxyHttpClientHandler.Proxy = null;
                    proxyHttpClientHandler.UseProxy = false;
                }

                string result = null;
                LogHelper.Info("request: " + requestString, "JDWuJieApiLog");
                using (HttpClient httpClient = new HttpClient(proxyHttpClientHandler))
                {
                    string fullurl = string.Format(url + "?app_key={0}&customerId={1}&method={2}", appkey, customerId, method);
                    var content = new StringContent(requestString, Encoding.UTF8, "application/json");
                    var response = httpClient.DoSign(credentials, "xohk7ybhwien").PostAsync(fullurl, content).Result;
                    result = response.Content?.ReadAsStringAsync().Result;
                }

                var responseObject = JObject.Parse(result);
                if (responseObject.GetJsonObjectStringValue("code") == "0000")
                {
                    var apiResponse = responseObject.GetJsonObject("extendProps");
                    JObject response = new JObject();
                    response["orderId"] = orderId;
                    response["waybillCode"] = apiResponse.GetJsonObjectStringValue("waybillCode");
                    response["waybillFilePath"] = CreateWaybillPDF(response, config, apiResponse.GetJsonObjectStringValue("waybillData")).GetJsonObjectStringValue("waybillFilePath");
                    return response;
                }
                else
                {
                    LogHelper.Info("response: " + result, "JDWuJieApiLog");
                    throw ExceptionHelper.GenException("@E210000002", responseObject.GetJsonObjectStringValue("message"));
                }
            }
            catch (BaseException ex)
            {
                if (!string.IsNullOrEmpty(ex.Message))
                    throw ex;
                throw new Exception(ex.Code);
            }
            catch (Exception ex)
            {
                LogHelper.Error("JDWuJie CreateWaybill fail", ex, "JDWuJieApiLog");
                throw new Exception("@E210000001");
            }
        }

        public JObject CreateWaybillPDF(JObject waybill, JObject config, string waybillData)
        {
            string path = "constant.jingdongWaybillConfig";
            string waybillFileDir = config.GetNecessaryJsonObjectStringValue("waybillfiledir", path);
            string waybillFileUrl = config.GetJsonObjectStringValue("waybillfileurl");

            string waybillCode = waybill.GetNecessaryJsonObjectStringValue("waybillCode");
            string orderId = waybill.GetNecessaryJsonObjectStringValue("orderId");
            try
            {
                if (string.IsNullOrWhiteSpace(waybillData))
                    throw new Exception("没有面单数据");

                byte[] bytes = Convert.FromBase64String(waybillData);

                string fileName = waybillCode + ".pdf";
                string filePath = waybillFileDir.StartsWith(@"\\") ? waybillFileDir : Utils.GetMapPath(waybillFileDir);
                if (!Directory.Exists(filePath))
                {
                    Directory.CreateDirectory(filePath);
                }

                using (PdfDocument document = new PdfDocument())
                {
                    PdfPage page = document.AddPage();
                    page.Size = PdfSharp.PageSize.A4;
                    page.Orientation = PdfSharp.PageOrientation.Landscape;

                    // Get an XGraphics object for drawing
                    XGraphics gfx = XGraphics.FromPdfPage(page, XGraphicsUnit.Millimeter);
                    using (var ms = new System.IO.MemoryStream(bytes))
                    using (XImage image = XImage.FromStream(ms))
                    {
                        gfx.DrawImage(image, 21, 21, 100, 150);
                        gfx.DrawImage(image, 176, 21, 100, 150);
                    }
                    document.Save(Path.Combine(filePath, fileName));
                }

                if (!string.IsNullOrWhiteSpace(waybillFileUrl) && !waybillFileUrl.EndsWith("/"))
                    waybillFileUrl += "/";

                var response = new JObject();
                response["orderId"] = orderId;
                response["waybillCode"] = waybillCode;
                response["waybillFilePath"] = fileName;
                if (!string.IsNullOrWhiteSpace(waybillFileUrl))
                    response["waybillFileURL"] = waybillFileUrl + fileName;
                return response;
            }
            catch (BaseException ex)
            {
                if (!string.IsNullOrEmpty(ex.Message))
                    throw ex;
                throw new Exception(ex.Code);
            }
            catch (Exception ex)
            {
                LogHelper.Error("JDWuJie CreateWaybillPDF fail", ex, "JDWuJieApiLog");
                throw new Exception("@E210000003");
            }
        }

        private static JObject SplitAddress(string address)
        {
            if (address == null)
                address = string.Empty;

            string province = null;
            string city = null;
            string country = null;

            address = address.Trim();
            var matches1 = System.Text.RegularExpressions.Regex.Matches(address, @"^[^省]+省|[^自治区]+自治区|北京市|天津市|上海市|重庆市");
            if (matches1.Count > 0)
            {
                province = matches1[0].Groups[0].Value;
                address = address.Substring(province.Length);
            }
            else
            {
                province = address.Substring(0, 2);
                address = address.Substring(2);
            }

            address = address.Trim();
            var matches2 = System.Text.RegularExpressions.Regex.Matches(address, @"^[^市]+市|[^自治州]+自治州|[^盟]+盟");
            if (matches2.Count > 0)
            {
                city = matches2[0].Groups[0].Value;
                address = address.Substring(city.Length);
            }
            else
            {
                city = address.Substring(0, 2);
                address = address.Substring(2);
            }

            address = address.Trim();

            var matches3 = System.Text.RegularExpressions.Regex.Matches(address, @"^[^县]+县|[^旗]+旗|.+区");
            if (matches3.Count > 0)
            {
                country = matches3[0].Groups[0].Value;
                address = address.Substring(country.Length);
            }
            else
            {
                country = address.Substring(0, 2);
                address = address.Substring(2);
            }

            return new JObject()
            {
                { "provinceName", province },
                { "cityName", city },
                { "countryName", country },
                { "address", province + city + country + address }
            };
        }
    }
}
